package com.demo.camunda.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.metadata.CellExtra;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.demo.camunda.dao.SqmWarningMappingDao;
import com.demo.camunda.entity.Msgclient;
import com.demo.camunda.entity.SqmWarningBase;
import com.demo.camunda.entity.SqmWarningMapping;
import com.demo.camunda.service.impl.uploadExcelImpl;
import com.demo.camunda.util.ExecptionExecution.ServiceException;
import com.demo.camunda.util.StaticValue;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import static com.sun.jmx.snmp.ThreadContext.contains;

@Slf4j
public class ImportListener<T> implements ReadListener<T> {


    private final uploadExcelImpl excel;

    private final SqmWarningMappingDao sqmWarningMappingDao;


    /**
     * 每隔4500条存储数据库，然后清理list ，方便内存回收
     */
    private static final int BATCH_COUNT = 4096;
    /**
     * 缓存的数据
     */
    private List<SqmWarningBase> cachedDataList = new ArrayList<>(0);

    private final AtomicInteger count = new AtomicInteger(0);

    private List<String> ExcelTitle = new ArrayList<>();

    private List<SqmWarningMapping> sqmWarningMappingsColumn;

    private Map<String,String> ExcelTitleToExcelValue = new HashMap<>(64);

    private Map<String,String> ColumnToExcelValue = new HashMap<>(64);


    public ImportListener(uploadExcelImpl excel, SqmWarningMappingDao sqmWarningMappingDao) {
        this.excel = excel;
        this.sqmWarningMappingDao = sqmWarningMappingDao;
    }


    @Override
    public   void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {


        String  Vender = "IRI";
        String  part =  "MB with Dome";

        for (Map.Entry<Integer, ReadCellData<?>> headMapEntry : headMap.entrySet()) {
        //    log.info("head的key:{}，head的value:{} ",headMapEntry.getKey(), headMapEntry.getValue());
            ExcelTitle.add(headMapEntry.getValue().getStringValue());
        }
        LambdaQueryWrapper<SqmWarningMapping> lambdaQueryWrapper = new LambdaQueryWrapper<SqmWarningMapping>()
                .eq(SqmWarningMapping::getVender,Vender)
                .eq(SqmWarningMapping::getPart,part);
        sqmWarningMappingsColumn = sqmWarningMappingDao.selectList(lambdaQueryWrapper);
      for(int i = 0 ; i < sqmWarningMappingsColumn.size() ; i++){
          //如果excel表头有mapping中column中的字段，就跳过
          if(ExcelTitle.contains(sqmWarningMappingsColumn.get(i).getColumn())){
            continue;
          }else{
             // throw  new ServiceException("無"+sqmWarningMappings.get(i).getColumn()+"此欄位存在excel中");
              //todo 移动文件道error文件夹中，并且王error表中插入数据
          }
      }


        log.info("ExcelTitle");

    }
    @Override
    public void invoke(T entity, AnalysisContext analysisContext) {
        count.addAndGet(1);

        //填充入库对象的属性值
        cachedDataList.add(FillPropertyValue(entity));
        // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
        if (cachedDataList.size() >= BATCH_COUNT) {

      //      excel.insertList((List<SqmWarningBase>) cachedDataList);
            //  batchInsert();
            // 存储完成清理 list
            //cachedDataList.clear();
            cachedDataList = new ArrayList<>(0);
        }
    }


    private SqmWarningBase FillPropertyValue(T entity){
        SqmWarningBase sqmWarningBase = new SqmWarningBase();
        // 获取该对象的Class
        Class objClass = SqmWarningBase.class;
        try {
            // 获取所有的属性数组
            Field[] fields = objClass.getDeclaredFields();

            Map map = new HashMap((Map) entity);
            for (int m = 0 ; m<map.size();m++) {
                ExcelTitleToExcelValue.put(ExcelTitle.get(m), (String) map.get(m));
            }

            Iterator iterator = ExcelTitleToExcelValue.keySet().iterator();
            while (iterator.hasNext()) {
                String next = (String) iterator.next();
                for(int j = 0 ;j< sqmWarningMappingsColumn.size();j++){
                    if(next.equals(sqmWarningMappingsColumn.get(j).getColumn())){
                        ColumnToExcelValue.put( StaticValue.map.get(sqmWarningMappingsColumn.get(j).getId()),ExcelTitleToExcelValue.get(next));


                        PropertyDescriptor propertyDescriptor = new PropertyDescriptor(StaticValue.map.get(sqmWarningMappingsColumn.get(j).getId()),objClass);
                        Method readMethod = propertyDescriptor.getWriteMethod();
                        readMethod.invoke(sqmWarningBase,ExcelTitleToExcelValue.get(next));
                        break;
                    }
                }
            }
//            Iterator ColumnToExcelValueIterator = ColumnToExcelValue.keySet().iterator();
//            while (ColumnToExcelValueIterator.hasNext()) {
//                String next = (String) ColumnToExcelValueIterator.next();
//                for (Field field : fields) {
//                    String name = field.getName();
//                    if(name.equals(next)){
//                        PropertyDescriptor propertyDescriptor = new PropertyDescriptor(name,objClass);
//                        Method readMethod = propertyDescriptor.getWriteMethod();
//                        readMethod.invoke(sqmWarningBase,ColumnToExcelValue.get(next));
//                    }
//                }
//            }

            //过滤掉表中有的字段
            List<String> ColumnList = sqmWarningMappingsColumn.stream().map(SqmWarningMapping::getColumn).collect(Collectors.toList());
            List<String> VariableJson = ExcelTitleToExcelValue.keySet()
                    .stream().filter(f -> !ColumnList.contains(f)).collect(Collectors.toList());
            ExcelTitleToExcelValue.keySet().stream().forEach( j ->{
                VariableJson.add(ExcelTitleToExcelValue.get(j));
            });
            sqmWarningBase.setVariableJson(JSON.toJSONString(VariableJson));
        } catch (Exception e) {
            e.printStackTrace();
        }


//        for(int i = 0 ; i <sqmWarningMappingsColumn.size();i++){
//
//            if(sqmWarningMappingsColumn.get(i))
//                StaticValue.map.get(i+1)
//                ColumnToExcel
//        }


        return sqmWarningBase;
    }
    @Override
    public void extra(CellExtra extra, AnalysisContext context) {

    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {

        if (count.get() > 0 && CollectionUtils.isNotEmpty(cachedDataList)) {
       //     excel.insertList((List<SqmWarningBase>) cachedDataList);
            log.info("第1个sheet一共获取了:{}条数据", count.get());
            //batchInsert();
        }
        log.info("第1个sheet所有数据解析完成！");
    }


//    @Async(value="myExecutor")
//    public void batchInsert() {
//        log.info("{}条数据，开始存储数据库!", count.get());
//
//        log.info(Thread.   ().getName());
//
//        if(CollectionUtils.isNotEmpty(cachedDataList)){
//            baseDaoMapper.insertList((List<com.demo.camunda.entity.Msgclient>) cachedDataList);
//        }
//
//
//
//        log.info("存储数据库成功!");
//    }

    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {

    }


    @Override
    public boolean hasNext(AnalysisContext context) {
        return true;
    }

}